package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.example.common.result.Result;
import com.example.common.util.SpringContextUtil;
import com.example.controller.ApprovalController;
import com.example.entity.activiti.ApprovalVo;
import com.example.entity.activiti.FlowInfo;
import com.example.entity.activiti.TaskInfo;
import com.example.entity.dto.TaskInit;
import com.example.entity.yifei.Dscma;
import com.example.exception.BaseException;
import com.example.exception.CustomException;
import com.example.mapper.DscmaMapper;
import com.example.service.IActFlowCustomService;
import com.example.service.TaskInitService;
import com.example.untils.StringUtils;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ActFlowCommService {
    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private TaskInitService taskInitService;

    @Resource
    private DscmaMapper dscmaMapper;

    /**
     * 部署流程定义
     */
    public void saveNewDeploy(FlowInfo flowInfo) {
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource(flowInfo.getFilepath()) // 添加bpmn资源
                .name(flowInfo.getFlowkey())
                .deploy();
//        4、输出部署信息
        System.out.println("流程部署id：" + deployment.getId());
        System.out.println("流程部署名称：" + deployment.getName());
    }

    /**
     * 获取流程用户自定义信息
     * @return
     */
    public List<Map> getTaskInit() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().latestVersion().list();
        List list1 = new ArrayList<Map>();
        list.forEach(processDefinition -> {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            Process mainProcess = bpmnModel.getMainProcess();
            Map map = new HashMap<>();
            //List list=new ArrayList<>();
            Collection<FlowElement> flowElements = mainProcess.getFlowElements();
            List list2 = new ArrayList<>();
            flowElements.forEach(flowElement -> {
                if ((flowElement instanceof UserTask&&(!flowElement.getName().equals("上报")))) {
                    Map map1 = new HashMap<>();
                    map1.put("taskId", flowElement.getId());
                    map1.put("taskName", flowElement.getName());
                    map1.put("documentation", flowElement.getDocumentation());
                    List<TaskInit> taskInits = taskInitService.selectAllByFormKeyAndTaskId(processDefinition.getKey(), flowElement.getId());
                    if (!taskInits.isEmpty()){
                        TaskInit taskInit = taskInits.get(0);
                        map1.put("assignee",taskInit.getAssignee());
                        map1.put("candidateUsers",taskInit.getCandidateUsers());
                    }
                    list2.add(map1);
                }
            });
        /*for (FlowElement flowElement : mainProcess.getFlowElements()) {
                if (!(flowElement instanceof SequenceFlow)){
                    System.out.println("节点ID: " + flowElement.getId());
                    System.out.println("节点名称: " + flowElement.getName());
                    System.out.printf("任务节点描述"+flowElement.getDocumentation());

                }
            }*/
            map.put("formKey", processDefinition.getKey());
            map.put("InsName",processDefinition.getDescription());
            map.put("TaskList", list2);
            list1.add(map);
        });
        return list1;
    }

    /**
     * 获取流程用户自定义信息 8月1日
     * @return
     */
    public List<Map> getTaskInits() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().latestVersion().list();
        List list1 = new ArrayList<Map>();
        list.forEach(processDefinition -> {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            Process mainProcess = bpmnModel.getMainProcess();
            Map map = new HashMap<>();
            //List list=new ArrayList<>();
            Collection<FlowElement> flowElements = mainProcess.getFlowElements();
            List list2 = new ArrayList<>();
            flowElements.forEach(flowElement -> {
                if ((flowElement instanceof UserTask&&(!flowElement.getName().equals("上报")))) {
                    Map map1 = new HashMap<>();
                    map1.put("taskId", flowElement.getId());
                    map1.put("taskName", flowElement.getName());
                    map1.put("documentation", flowElement.getDocumentation());
                    List<TaskInit> taskInits = taskInitService.selectAllByFormKeyAndTaskId(processDefinition.getKey(), flowElement.getId());
                    if (!taskInits.isEmpty()){
                        TaskInit taskInit = taskInits.get(0);
                        map1.put("assignee",taskInit.getAssignee());
                        map1.put("candidateUsers",taskInit.getCandidateUsers());
                    }
                    List<TaskInit> taskInits1 = taskInitService.selectAllByFormKeyAndTaskIds(processDefinition.getKey(), flowElement.getId());
                    if (!taskInits1.isEmpty()){
                        TaskInit taskInit = taskInits1.get(0);
                        map1.put("candidateUsersCs",taskInit.getCandidateUsers());
                    }
                    list2.add(map1);
                }
            });
        /*for (FlowElement flowElement : mainProcess.getFlowElements()) {
                if (!(flowElement instanceof SequenceFlow)){
                    System.out.println("节点ID: " + flowElement.getId());
                    System.out.println("节点名称: " + flowElement.getName());
                    System.out.printf("任务节点描述"+flowElement.getDocumentation());

                }
            }*/
            map.put("formKey", processDefinition.getKey());
            map.put("InsName",processDefinition.getDescription());
            map.put("TaskList", list2);
            list1.add(map);
        });
        return list1;
    }

    @Autowired
    private ApprovalController approvalController;
    /**
     * 启动流程实例
     */
    public ProcessInstance startProcess(String formKey, String beanName, String bussinessKey, String id, String userName, String leader) {
        System.out.println("名称:"+beanName);
        IActFlowCustomService customService = (IActFlowCustomService) SpringContextUtil.getBean(beanName);
        Map<String, Object> variables = customService.setvariables(id, userName);
        variables.put("initiator", userName);
        variables.put("leader", leader);
//		启动流程
        log.info("【启动流程】，formKey ：{},bussinessKey:{}", formKey, bussinessKey);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(formKey, bussinessKey, variables);

        if (processInstance==null){
            throw new BaseException("启动审批流失败");
        }
        runtimeService.setProcessInstanceName(processInstance.getProcessInstanceId(),variables.get("processInsName").toString());
        //		修改业务的状态
        Result result = approvalController.approvalStart(id);
        if (!result.getCode().equals("200")) {
            throw new BaseException(result.getMsg());
        }
        return processInstance;
    }

    /**
     * 查看个人任务列表
     */
    public List<Task> myTaskList(String userName) {
        /**
         * 根据负责人  查询任务
         */
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> list = taskQuery.taskAssignee(userName).orderByTaskCreateTime().desc().list();
        if (list==null){
            throw new BaseException("查询不到该用户的任务列表，服务出错");
        }
        return list;
    }

    /**
     * 用户当前任务分页
     *
     * @param current  当前页码
     * @param size     页大小
     * @param userName 用户名
     * @param formKey  业务key
     * @return
     */
    public Result myTaskPage(int current, int size, String userName, String formKey,Date dateafter,Date dateBefore,String businessKey,String applicant) {

        /**
         * 根据负责人  查询任务
         */
        TaskQuery taskQuery = taskService.createTaskQuery();
        PageInfo pageInfo = new PageInfo<>();
        List<Task> list;
        Long count;
        if (!userName.equals("admin")) {
            taskQuery.taskCandidateOrAssigned(userName);
        }
        if (StringUtils.isNotEmpty(formKey))
        {
            taskQuery.processDefinitionKey(formKey);
        }
        if (dateafter!=null){
            taskQuery.taskCreatedAfter(dateafter);
        }
        if (dateBefore!=null){
            taskQuery.taskCreatedBefore(dateBefore);
        }
        if (StringUtils.isNotEmpty(businessKey)){
            taskQuery.processInstanceBusinessKey(businessKey);
        }
        if (StringUtils.isNotEmpty(applicant)){
            taskQuery.processVariableValueEquals("initiator",applicant);
        }
        taskQuery.active().orderByTaskCreateTime().desc();
        list=taskQuery.listPage(Math.max(0, (current - 1) * size), size);
        count=taskQuery.count();
        Map<String,Object> map = new HashMap<>();
        log.info("tasklist={}", list);
        if (list.isEmpty()) {
            map.put("pages", pageInfo.getPages());
            map.put("total", pageInfo.getTotal());
            map.put("list", pageInfo.getList());
            return Result.success(map);
        }
        List<ApprovalVo> list1 = new ArrayList<>();
        for (Task task : list) {
//            Map<String, Object> map = new HashMap<String, Object>();
            String executionId = task.getExecutionId();
            String initiator = runtimeService.getVariable(executionId, "initiator", String.class);
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            businessKey = processInstance.getBusinessKey();
            String[] split = businessKey.split(":");
            String selectFormKey = split[0];
            String TC001 = split[1];
            String TC002 = split[2];
            String processInstanceId = task.getProcessInstanceId();
            Date createTime = task.getCreateTime();
            String format = SimpleDateFormat.getDateTimeInstance().format(createTime);

            ApprovalVo approvalVo = new ApprovalVo();
            approvalVo.setProcessInstanceId(processInstanceId);
            approvalVo.setProcessDefinitionId(task.getProcessDefinitionId());
            approvalVo.setExecutionId(executionId);
            approvalVo.setApplicant(initiator);
            approvalVo.setType(task.getFormKey());
            approvalVo.setTaskid(task.getId());
            approvalVo.setTaskname(task.getName());
            approvalVo.setDescription(task.getDescription());
            approvalVo.setAssignee(task.getAssignee());
            approvalVo.setFormKey(selectFormKey);
            approvalVo.setTc001(TC001);
            approvalVo.setTc002(TC002);
            approvalVo.setPriority(task.getPriority());
            approvalVo.setOwner(task.getOwner());
            approvalVo.setDelegationState(task.getDelegationState());
            approvalVo.setCreateTime(format);
            approvalVo.setTaskDefinitionKey(task.getTaskDefinitionKey());
            approvalVo.setDueDate(task.getDueDate());
            approvalVo.setCategory(task.getCategory());
            approvalVo.setParentTaskId(task.getParentTaskId());
            approvalVo.setTenantId(task.getTenantId());
            list1.add(approvalVo);
        }
        pageInfo.setList(list1);
        pageInfo.setTotal(count);
        pageInfo.setPageSize(size);
        pageInfo.setPageNum(current);
        map.put("pages", pageInfo.getPages());
        map.put("total", pageInfo.getTotal());
        map.put("list", pageInfo.getList());
        return Result.success(map);
    }

    /**
     * 查看个人任务信息
     */
   /* public Object myTaskInfoList(String taskId) {
        Object variable = taskService.getVariable(taskId, "object");
        String bussinessKey =(String) taskService.getVariable(taskId, "bussinessKey");
        String[] split = bussinessKey.split(":");
        String formKey=split[0];
        if (formKey.equals("purtc")){
            ActPurchaseVo actPurchaseVo= new ActPurchaseVo(formKey);
            BeanUtils.copyProperties(variable,actPurchaseVo);
            log.info("taskInfo-={}", actPurchaseVo);
            return actPurchaseVo;
        }

        else {
            return variable;
        }
        //Object variable = runtimeService.getVariable(taskId, "object");
    }*/


    /**
     * 完成提交任务
     */
    public void completeProcess(String remark, String taskId, String userId, Map<String, Object> map) {


        //任务Id 查询任务对象
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (task == null) {
            log.error("completeProcess - task is null!!");
            return;
        }


        //任务对象  获取流程实例Id
        String processInstanceId = task.getProcessInstanceId();

        //设置审批人的userId
        //Authentication.setAuthenticatedUserId(userId);

        //添加记录
        taskService.addComment(taskId, processInstanceId, remark);
        System.out.println("-----------完成任务操作 开始----------");
        System.out.println("任务Id=" + taskId);
        System.out.println("负责人id=" + userId);
        System.out.println("流程实例id=" + processInstanceId);
        //完成办理
        taskService.complete(taskId, map);
        System.out.println("-----------完成任务操作 结束----------");
    }

    public void completeProcess(String remark, String username, String taskId, String advice) {

        //任务Id 查询任务对象
        Task task = taskService.createTaskQuery().taskCandidateOrAssigned(username).taskId(taskId).singleResult();
        System.out.println("Task"+task);
        log.info("Task{}", task);
        if (task == null) {
            throw new BaseException("任务不存在或已被他人完成");
        }
//        if (!task.getAssignee().equals(username)) {
        taskService.claim(taskId, username);
//        }
        log.info("审批意见为{}", advice);
        //任务对象  获取流程实例Id
        String processInstanceId = task.getProcessInstanceId();

        //设置审批人的userId
        //Authentication.setAuthenticatedUserId(userId);

        //添加记录
        try {
            taskService.addComment(taskId, processInstanceId, advice);
        } catch (ActivitiException e) {
            System.out.printf(e.getMessage());
            throw new BaseException("申请被挂起，现在无法审批！");
        }
        System.out.println("-----------完成任务操作 开始----------");
        System.out.println("任务Id=" + taskId);
        System.out.println("完成人=" + username);
        System.out.println("流程实例id=" + processInstanceId);
        try{
            //完成办理
            if (remark.equals("同意")) {
                Map map = new HashMap<>();
                map.put("code", true);
                map.put("result", "审批中");
                taskService.setVariableLocal(taskId,"taskResult",true);
                System.out.println("Map:"+map);
                taskService.complete(taskId, map);
            } else {
                Map map = new HashMap<>();
                map.put("code", false);
                map.put("result", "驳回");
                taskService.setVariableLocal(taskId,"taskResult",false);
                taskService.complete(taskId, map);
            }
            System.out.println("-----------完成任务操作 结束----------");
        }catch (Exception e){
            throw new CustomException("500","流程未初始化，请先自定义流程负责人");
        }
    }

    /**
     * 查询当前用户发起的流程实例
     *
     * @param userName 用户名
     */
    public PageInfo allProcessIns(String userName, int current, int size) {
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        List<ProcessInstance> list;
        long count;
        PageInfo pageInfo = new PageInfo<>();
        if (userName.equals("admin")) {
            list = processInstanceQuery.orderByProcessInstanceId().desc().listPage(Math.max(0, (current - 1) * size), size);
            count = processInstanceQuery.orderByProcessInstanceId().desc().count();
        } else {
            list = processInstanceQuery.variableValueEquals("initiator", userName).orderByProcessInstanceId().desc().listPage(Math.max(0, (current - 1) * size), size);
            count = processInstanceQuery.variableValueEquals("initiator", userName).orderByProcessInstanceId().desc().count();
        }
        List<Map> mapList = new ArrayList<>();
        list.forEach(processInstance -> {
            ProcessInstance process = (ProcessInstance) processInstance;
            HistoricActivityInstance activitie = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(process.getProcessInstanceId())
                    .unfinished() // 只查询未完成的活动
                    .singleResult();
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(process.getProcessInstanceId()).finished().orderByHistoricTaskInstanceEndTime().desc().list().get(0);
            List<Comment> taskComments = taskService.getTaskComments(historicTaskInstance.getId());

            //List<Comment> processInstanceComments = taskService.getProcessInstanceComments(process.getProcessInstanceId());
            /*for (HistoricActivityInstance activity : activities) {
                System.out.println("当前进度: " + activity.getActivityName()+"负责人"+activity.getAssignee());
            }*/
            Map map = new HashMap<>();
            map.put("processDefinitionId", process.getProcessDefinitionId());
            map.put("processInstanceId", process.getProcessInstanceId());
            map.put("description", process.getDescription());
            map.put("processInstanceName", process.getName());
            String businessKey = process.getBusinessKey();
            String[] split = businessKey.split(":");
            map.put("type", split[0]);
            map.put("TC001", split[1]);
            map.put("TC002", split[2]);
            String format = SimpleDateFormat.getDateTimeInstance().format(process.getStartTime());
            map.put("startTime", format);
            Map<String, Object> variables = runtimeService.getVariables(activitie.getExecutionId());
            map.put("applicant", variables.get("initiator"));
            map.put("result", variables.get("result"));
            map.put("advice", taskComments.get(0).getFullMessage());
            map.put("currentProgress", activitie.getActivityName());
            map.put("assignee", activitie.getAssignee());
            map.put("isSuspended", process.isSuspended());
            mapList.add(map);
        });
        pageInfo.setList(mapList);
        pageInfo.setPageNum(current);
        pageInfo.setPageSize(size);
        pageInfo.setTotal(count);
        return pageInfo;
    }

    /**
     * 查询当前用户发起的历史流程实例
     * @param userName
     * @param current
     * @param size
     * @return
     */
    public PageInfo allHisProcessIns(String userName, int current, int size) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        List<HistoricProcessInstance> list;
        long count;
        PageInfo pageInfo = new PageInfo<>();
        if (userName.equals("admin")) {
            list = historicProcessInstanceQuery.finished().orderByProcessInstanceId().desc().listPage(Math.max(0, (current - 1) * size), size);
            count = historicProcessInstanceQuery.finished().orderByProcessInstanceId().desc().count();
        } else {
            list = historicProcessInstanceQuery.variableValueEquals("initiator", userName).finished().orderByProcessInstanceId().desc().listPage(Math.max(0, (current - 1) * size), size);
            count = historicProcessInstanceQuery.variableValueEquals("initiator", userName).finished().orderByProcessInstanceId().desc().count();
        }
        List<Map> mapList = new ArrayList<>();
        list.forEach(processInstance -> {
            HistoricProcessInstance process = (HistoricProcessInstance) processInstance;
            //String endActivityId = process.getEndActivityId();
            //HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(endActivityId).singleResult();
            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(process.getId()).variableName("initiator").singleResult();
            HistoricVariableInstance historicVariableInstance2 = historyService.createHistoricVariableInstanceQuery().processInstanceId(process.getId()).variableName("result").singleResult();

            Map map = new HashMap<>();
            map.put("processDefinitionId", process.getProcessDefinitionId());
            map.put("processInstanceId", process.getId());
            map.put("description", process.getDescription());
            map.put("processInstanceName", process.getName());
            String businessKey = process.getBusinessKey();
            String[] split = businessKey.split(":");
            map.put("type", split[0]);
            map.put("TC001", split[1]);
            map.put("TC002", split[2]);
            String startTime = SimpleDateFormat.getDateTimeInstance().format(process.getStartTime());
            map.put("startTime", startTime);
            String endTime=SimpleDateFormat.getDateTimeInstance().format(process.getEndTime());
            map.put("endtime",endTime);
            map.put("applicant", historicVariableInstance.getValue());
            map.put("result", historicVariableInstance2.getValue());
            mapList.add(map);
        });
        pageInfo.setList(mapList);
        pageInfo.setPageNum(current);
        pageInfo.setPageSize(size);
        pageInfo.setTotal(count);
        return pageInfo;
    }

    /**
     * 历史任务
     * @param current
     * @param size
     * @param userName
     * @return
     */
    public PageInfo searchUserHisTask(int current, int size, String userName, String formKey, Date dateAfter, Date dateBefore, String businessKey, String applicant) {
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
        if (!userName.equals("admin")) {
            historicTaskInstanceQuery.taskAssignee(userName);
        }
        if (StringUtils.isNotEmpty(formKey))
        {
            historicTaskInstanceQuery.processDefinitionKey(formKey);
        }
        if (dateAfter!=null){
            historicTaskInstanceQuery.taskCreatedAfter(dateAfter);
        }else {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, -1);
            Date oneMonthAgo = calendar.getTime();
            historicTaskInstanceQuery.taskCreatedAfter(oneMonthAgo);
        }
        if (dateBefore!=null){
            historicTaskInstanceQuery.taskCreatedBefore(dateBefore);
        }
        if (StringUtils.isNotEmpty(businessKey)){

            historicTaskInstanceQuery.processInstanceBusinessKeyLike("%"+businessKey+"%");
        }
        if (StringUtils.isNotEmpty(applicant)){
            historicTaskInstanceQuery.processVariableValueEquals("initiator",applicant);
        }
        historicTaskInstanceQuery.finished().orderByHistoricTaskInstanceEndTime().desc();
        List<HistoricTaskInstance> historicTaskInstances = historicTaskInstanceQuery.listPage(Math.max(0, (current - 1) * size), size);
        Long count=historicTaskInstanceQuery.count();
        log.info("历史任务列表：{}",historicTaskInstances);
        if (historicTaskInstances.isEmpty()) {
            return null;
        }
        List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
        for (HistoricTaskInstance task :historicTaskInstances){
            Map<String, Object> map = new HashMap<String, Object>();
            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(task.getProcessInstanceId()).variableName("initiator").excludeTaskVariables().singleResult();
            HistoricVariableInstance historicVariableInstance1 = historyService.createHistoricVariableInstanceQuery().taskId(task.getId()).variableName("taskResult").singleResult();
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            businessKey = processInstance.getBusinessKey();
            String[] split = businessKey.split(":");
            String selectFormKey = split[0];
            String TC001 = split[1];
            String TC002 = split[2];
            String processInstanceId = task.getProcessInstanceId();
            String startTime = SimpleDateFormat.getDateTimeInstance().format(task.getStartTime());
            String endTime= task.getEndTime()==null? "缺省":SimpleDateFormat.getDateTimeInstance().format(task.getEndTime());
            String deleteReason = task.getDeleteReason();
            if (StringUtils.isNotEmpty(deleteReason)){
                map.put("isDeleted",true);
                map.put("deleteReason",deleteReason);
            }else {
                map.put("isDeleted",false);
            }
            map.put("processInstanceId", processInstanceId);
            map.put("processDefinitionId", task.getProcessDefinitionId());
            map.put("applicant", historicVariableInstance.getValue());
            map.put("type", task.getFormKey());
            map.put("taskid", task.getId());
            map.put("taskname", task.getName());
            map.put("description", task.getDescription());
            map.put("assignee", task.getAssignee());
            map.put("formKey", selectFormKey);
            map.put("TC001", TC001);
            map.put("TC002", TC002);
            map.put("priority", task.getPriority());
            map.put("taskResult",historicVariableInstance1==null?"暂无结果":historicVariableInstance1.getValue());
            map.put("createTime", startTime);
            map.put("endTime",endTime);
            listmap.add(map);
        }
        PageInfo<Map<String,Object>> pageInfo = new PageInfo<>(listmap);
        pageInfo.setTotal(count);
        return pageInfo;
    }

    /**
     * 拾取组任务
     * @param taskId
     * @param userName
     * @return
     */
    public boolean claimTask(String taskId, String userName) {
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateGroup(userName)//根据组查询
                .singleResult();
        if (task!=null){
            taskService.claim(taskId, userName);
            System.out.println("任务拾取成功");
            return true;
        }
        return false;
    }

    /**
     * 查询组任务分页
     * @param current
     * @param size
     * @param groupName
     * @param formKey
     * @return
     */
    public PageInfo groupTaskPage(int current, int size, String groupName, String formKey) {
        /**
         * 根据负责人  查询任务
         */
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> list;
        Long count;
        if (groupName.equals("admin")) {
            list = taskQuery.orderByTaskCreateTime().desc().listPage(Math.max(0, (current - 1) * size), size);
            count=taskQuery.orderByTaskCreateTime().desc().count();
        } else {
            list = taskQuery.taskCandidateGroup(groupName).processDefinitionKey(formKey).orderByTaskCreateTime().desc().listPage(Math.max(0, (current - 1) * size), size);
        count=taskQuery.taskCandidateGroup(groupName).processDefinitionKey(formKey).orderByTaskCreateTime().desc().count();
        }
        log.info("tasklist={}", list);
        List<Map<String, Object>> listmap = new ArrayList<>();
        for (Task task : list) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("taskid", task.getId());
            map.put("taskname", task.getName());
            map.put("description", task.getDescription());
            map.put("priority", task.getPriority());
            map.put("owner", task.getOwner());
            map.put("assignee", task.getAssignee());
            map.put("delegationState", task.getDelegationState());
            map.put("processInstanceId", task.getProcessInstanceId());
            map.put("executionId", task.getExecutionId());
            map.put("processDefinitionId", task.getProcessDefinitionId());
            map.put("createTime", task.getCreateTime());
            map.put("taskDefinitionKey", task.getTaskDefinitionKey());
            map.put("dueDate", task.getDueDate());
            map.put("category", task.getCategory());
            map.put("parentTaskId", task.getParentTaskId());
            map.put("tenantId", task.getTenantId());
            listmap.add(map);
        }
        // String[] ps={"id","assignee","processInstanceId","executionId","processDefinitionId","description","createTime"}
        PageInfo pageInfo = new PageInfo<>(listmap);
        pageInfo.setTotal(count);
        return pageInfo;
    }

    /**
     * 归还组任务
     * @param taskId
     * @param userName
     * @return
     */
    public boolean returnTask(String taskId, String userName) {
        Task task = taskService
                .createTaskQuery()
                .taskId(taskId)
                .taskAssignee(userName)
                .singleResult();
        if (task!=null){
            taskService.setAssignee(taskId, null);
            return true;
        }
        return false;
    }

    /**
     * 获取单据的审核状态
     * @param businessKey
     * @param formKey
     * @return
     */
    public String getCurStatus(String businessKey,String formKey) {
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).notDeleted().orderByProcessInstanceStartTime().desc().singleResult();
        if (processInstance==null){
            return "未开始";
        }
        if (processInstance.getEndTime()!=null) {
            return "审批完成";
        }

        HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).variableName("result").singleResult();
        if(historicVariableInstance==null){
            return "错误数据";
        }
        if (historicVariableInstance.getValue().equals("驳回")){
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstance.getId()).finished().orderByHistoricTaskInstanceEndTime().desc().list().get(0);
            List<Comment> taskComments = taskService.getTaskComments(historicTaskInstance.getId());
            return taskComments.get(0).getFullMessage();
        }
        final String[] res = {null};
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstance.getId()).list();
        list.forEach(ht->{
            if (ht.getEndTime()==null&&ht.getDeleteReason()==null){
                res[0] =ht.getName();
            }
        });
        return res[0];
    }

    /**
     * 判断是否有相同单据正在审核
     * @param bussinessKey
     * @param formkey
     * @return
     */
    public Boolean isOnly(String bussinessKey, String formkey) {
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(bussinessKey, formkey).list();
        if (list.isEmpty()){
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * 获取当前单据审核进度
     * @param businessKey
     * @param formKey
     * @return
     */
    public List<TaskInfo> getCurProcessState(String businessKey, String formKey) {
//        System.out.println("businessKey"+businessKey);
        //ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey, formKey).orderByProcessInstanceId().desc().list().get(0);
        List<HistoricProcessInstance> list1 = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).orderByProcessInstanceStartTime().desc().list();
        if (list1.isEmpty()){
            List<TaskInfo> taskInfoList=new ArrayList<>();
            TaskInfo taskInfo=new TaskInfo();
            taskInfo.setState("未开始审批");
            taskInfoList.add(taskInfo);
            return taskInfoList;
        }
        HistoricProcessInstance processInstance = list1.get(0);
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstance.getId()).orderByHistoricTaskInstanceStartTime().asc().list();
        List<TaskInfo> taskInfoList=new ArrayList<>();
        list.stream().forEach(hp->{
            //endTime不为空且deleteReason为空，此任务节点的审批已经结束
            if(hp.getEndTime()!=null && hp.getDeleteReason()==null){
                TaskInfo taskInfo=new TaskInfo();
                //获取任务id
                taskInfo.setTaskId(hp.getId());
                //获取任务节点名称
                taskInfo.setTaskName(hp.getName());
                //获取审批时间
                taskInfo.setEndTime(SimpleDateFormat.getDateTimeInstance().format(hp.getEndTime()));
                //获取审批人username
                taskInfo.setTaskAssignee(hp.getAssignee());
                Dscma dscma = this.dscmaMapper.selectOne(new LambdaQueryWrapper<Dscma>().eq(Dscma::getMa001, hp.getAssignee()));
                if (dscma!=null){
                    taskInfo.setTaskAssigneeName(dscma.getMa002());
                }
                //获取此审批节点开始时间
                taskInfo.setStartTime(SimpleDateFormat.getDateTimeInstance().format(hp.getStartTime()));
                //通过businessKey和表单key获取表单信息
                HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().taskId(hp.getId()).variableName("taskResult").singleResult();
                taskInfo.setResult((Boolean) historicVariableInstance.getValue());
                taskInfo.setState(taskService.getTaskComments(hp.getId()).get(0).getFullMessage());
                taskInfoList.add(taskInfo);
                if (!(Boolean) historicVariableInstance.getValue()) {
                    taskInfoList.clear();
                }
                //否则表示审批还未进行或者用户在这个节点已经主动撤销
            }else {
                TaskInfo taskInfo=new TaskInfo();
                //获取任务id
                taskInfo.setTaskId(hp.getId());
                //获取任务节点名称
                taskInfo.setTaskName(hp.getName());
                //获取审批人username
                taskInfo.setTaskAssignee(hp.getAssignee());
                //获取此审批节点开始时间
                taskInfo.setStartTime(SimpleDateFormat.getDateTimeInstance().format(hp.getStartTime()));
                //判断是否为用户主动撤销
                if(hp.getDeleteReason()!=null){
                    //填充撤销原因
                    taskInfo.setState(hp.getDeleteReason());
                }else {
                    //否则表示未审批
                    taskInfo.setState("未完成");
                }
                taskInfoList.add(taskInfo);
            }
        });
        return taskInfoList;
    }

    /*public void getCurProcessState2(String businessKey, String formKey) {
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).orderByProcessInstanceStartTime().desc().list().get(0);
        Execution execution = runtimeService.createExecutionQuery()
                .processDefinitionId(processInstance.getProcessDefinitionId()).onlyChildExecutions()
                .singleResult();
        // 如果流程实例存在，获取其节点（任务）
        if (execution != null) {
            // 获取与执行图关联的所有任务
            List<Task> tasks = taskService.createTaskQuery()
                    .executionId(execution.getId())
                    .list();
            // 输出任务信息
            for (Task task : tasks) {
                System.out.println("Task ID: " + task.getId());
                System.out.println("Task Name: " + task.getName());
                System.out.println("Assignee: " + task.getAssignee());
                HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().taskId(task.getId()).variableName("taskResult").singleResult();
                System.out.println("taskResult: " + historicVariableInstance==null ? "暂无" : historicVariableInstance.getValue());
                System.out.println("taskState: " + "zanwu");
                System.out.println("taskStart: " + task.getCreateTime());
            }
        }
    }*/

    /*public void getFlowImgByInstanceId(String businessKey, String formKey, HttpServletResponse response) {

        InputStream imageStream = null;
        try {
            //if (StringUtils.isEmpty(processInstanceId)) {
            //    return null;
            //}
            // 获取历史流程实例
            List<HistoricProcessInstance> list = historyService
                    .createHistoricProcessInstanceQuery()
                    .processInstanceBusinessKey(businessKey).orderByProcessInstanceStartTime().desc().list();
            if (list.isEmpty()) {
                return;
            }
            HistoricProcessInstance processInstance = list.get(0);
            // 获取流程中已经执行的节点，按照执行先后顺序排序
            List<HistoricActivityInstance> historicActivityInstances = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstance.getId())
                    .orderByHistoricActivityInstanceId()
                    .asc().list();
            // 高亮已经执行流程节点ID集合
            List<String> highLightedActivitiIds = new ArrayList<>();
            for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
                // 用默认颜色
                highLightedActivitiIds.add(historicActivityInstance.getActivityId());
            }
            // 正在执行的节点
            List<Execution> runTaskList = runtimeService.createExecutionQuery()
                    .processInstanceId(processInstance.getId())
                    .list();
            List<String> runningActivityIdList = new ArrayList<>();
            for (Execution execution : runTaskList) {
                if (!StringUtils.isEmpty(execution.getActivityId())) {
                    runningActivityIdList.add(execution.getActivityId());
                }
            }
            List<String> currIds = historicActivityInstances.stream()
                    .filter(item -> item.getEndTime() != null)
                    .map(HistoricActivityInstance::getActivityId).collect(Collectors.toList());

            // 获得流程引擎配置
            ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();

            BpmnModel bpmnModel = repositoryService
                    .getBpmnModel(processInstance.getProcessDefinitionId());
            // 高亮流程已发生流转的线id集合
            List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstances);
            //
            imageStream = new DefaultProcessDiagramGenerator().generateDiagram(
                    bpmnModel,
                    "png",
                    highLightedActivitiIds,//所有活动过的节点，包括当前在激活状态下的节点
                    currIds,//当前为激活状态下的节点
                    highLightedFlowIds,//活动过的线
                    "宋体",
                    "宋体",
                    "宋体",
                    processEngineConfiguration.getClassLoader(),
                    1.0,
                    runningActivityIdList);

            OutputStream out = null;
            out = response.getOutputStream();
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = imageStream.read(b)) != -1) {
                out.write(b, 0, len);
            }
            out.flush();


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (imageStream != null) {
                try {
                    imageStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }*/
    /*public List<String> getHighLightedFlows(BpmnModel bpmnModel,
                                            List<HistoricActivityInstance> historicActivityInstanceList) {
        //historicActivityInstanceList 是 流程中已经执行的历史活动实例
        // 已经流经的顺序流，需要高亮显示
        List<String> highFlows = new ArrayList<>();

        // 全部活动节点
        List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();

        // 拥有endTime的历史活动实例，即已经完成了的节点
        List<HistoricActivityInstance> finishedActivityInstancesList = new ArrayList<>();

        *//*
         * 循环的目的：
         *           获取所有的历史节点FlowNode并放入allHistoricActivityNodeList
         *           获取所有确定结束了的历史节点finishedActivityInstancesList
         *//*
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
            // 获取流程节点
            // bpmnModel.getMainProcess()获取一个Process对象
            FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
            allHistoricActivityNodeList.add(flowNode);

            // 如果结束时间不为空，表示当前节点已经完成
            if (historicActivityInstance.getEndTime() != null) {
                finishedActivityInstancesList.add(historicActivityInstance);
            }
        }

        FlowNode currentFlowNode;
        FlowNode targetFlowNode;
        HistoricActivityInstance currentActivityInstance;

        // 遍历已经完成的活动实例，从每个实例的outgoingFlows中找到已经执行的
        for (int k = 0; k < finishedActivityInstancesList.size(); k++) {
            currentActivityInstance = finishedActivityInstancesList.get(k);

            // 获得当前活动对应的节点信息以及outgoingFlows信息
            currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);

            // 当前节点的所有流出线
            List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();

            *//*
             * 遍历outgoingFlows并找到已经流转的  满足如下条件认为已经流转：
             * 1、当前节点是并行网关或者兼容网关，则通过outgoingFlows能够在历史活动中找到的全部节点均为已经流转
             * 2、当前节点是以上两种类型之外的，通过outgoingFlows查找到的时间最早的流转节点视为有效流转
             * (第二点有问题，有过驳回的，会只绘制驳回的流程线，通过走向下一级的流程线没有高亮显示)
             *//*
            if ("parallelGateway".equals(currentActivityInstance.getActivityType()) ||
                    "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
                // 遍历历史活动节点，找到匹配流程目标节点的
                for (SequenceFlow outgoingFlow : outgoingFlowList) {
                    // 获取当前节点流程线对应的下一级节点
                    targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(), true);

                    // 如果下级节点包含在所有历史节点中，则将当前节点的流出线高亮显示
                    if (allHistoricActivityNodeList.contains(targetFlowNode)) {
                        highFlows.add(outgoingFlow.getId());
                    }
                }
            } else {
                *//*
                 * 2、当前节点不是并行网关或者兼容网关
                 * 【已解决-问题】如果当前节点有驳回功能，驳回到申请节点，
                 * 则因为申请节点在历史节点中，导致当前节点驳回到申请节点的流程线被高亮显示，但实际并没有进行驳回操作
                 *//*
                List<Map<String, Object>> tempMapList = new ArrayList<>();

                // 当前节点ID
                String currentActivityId = currentActivityInstance.getActivityId();

                int size = historicActivityInstanceList.size();
                boolean ifStartFind = false;
                boolean ifFinded = false;
                HistoricActivityInstance historicActivityInstance;

                // 循环当前节点的所有流出线
                // 循环所有的历史节点
//                log.info("【开始】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
//                log.info("循环历史节点");

                for (int i = 0; i < size; i++) {
                    // // 如果当前节点流程线对应的下级节点在历史节点中，则该条流程线进行高亮显示（【问题】有驳回流程线时，即使没有进行驳回操作，因为申请节点在历史节点中，也会将驳回流程线高亮显示-_-||）
                    // if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
                    // Map<String, Object> map = new HashMap<>();
                    // map.put("highLightedFlowId", sequenceFlow.getId());
                    // map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
                    // tempMapList.add(map);
                    // // highFlows.add(sequenceFlow.getId());
                    // }

                    // 历史节点
                    historicActivityInstance = historicActivityInstanceList.get(i);
//                    log.info("第【{}/{}】个历史节点-ActivityId=【{}】", i + 1, size, historicActivityInstance.getActivityId());

                    // 如果循环历史节点中的id等于当前节点id，从当前历史节点继续先后查找是否有当前流程线等于的节点
                    // 历史节点的序号需要大于等于已经完成历史节点的序号，放置驳回重审一个节点经过两次时只取第一次的流出线高亮显示，第二次的不显示
                    if (i >= k && historicActivityInstance.getActivityId().equals(currentActivityId)) {
//                        log.info("第【{}】个历史节点和当前节点一致-ActivityId=【{}】", i + 1, historicActivityInstance.getActivityId());
                        ifStartFind = true;
                        // 跳过当前节点继续查找下一个节点
                        continue;
                    }
                    if (ifStartFind) {
//                        log.info("[开始]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);

                        ifFinded = false;
                        for (SequenceFlow sequenceFlow : outgoingFlowList) {
                            // 如果当前节点流程线对应的下级节点在其后面的历史节点中，则该条流程线进行高亮显示
                            // 【问题】
//                            log.info("当前流出线的下级节点=[{}]", sequenceFlow.getTargetRef());
                            if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
//                                log.info("当前节点[{}]需高亮显示的流出线=[{}]", currentActivityId, sequenceFlow.getId());
                                highFlows.add(sequenceFlow.getId());
                                // 暂时默认找到离当前节点最近的下一级节点即退出循环，否则有多条流出线时将全部被高亮显示
                                ifFinded = true;
                                break;
                            }
                        }
//                        log.info("[完成]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
                    }
                    if (ifFinded) {
                        // 暂时默认找到离当前节点最近的下一级节点即退出历史节点循环，否则有多条流出线时将全部被高亮显示
                        break;
                    }
                }
//                log.info("【完成】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
                // if (!CollectionUtils.isEmpty(tempMapList)) {
                // // 遍历匹配的集合，取得开始时间最早的一个
                // long earliestStamp = 0L;
                // String highLightedFlowId = null;
                // for (Map<String, Object> map : tempMapList) {
                // long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
                // if (earliestStamp == 0 || earliestStamp <= highLightedFlowStartTime) {
                // highLightedFlowId = map.get("highLightedFlowId").toString();
                // earliestStamp = highLightedFlowStartTime;
                // }
                // }
                // highFlows.add(highLightedFlowId);
                // }
            }
        }
        return highFlows;
    }*/
    public List<String> getHighLightedFlowsByIncomingFlows(BpmnModel bpmnModel,
                                                           List<HistoricActivityInstance> historicActivityInstanceList) {
        //historicActivityInstanceList 是 流程中已经执行的历史活动实例
        // 已经流经的顺序流，需要高亮显示
        List<String> highFlows = new ArrayList<>();

        // 全部活动节点(包括正在执行的和未执行的)
        List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();

        /*
         * 循环的目的：
         *           获取所有的历史节点FlowNode并放入allHistoricActivityNodeList
         *           获取所有确定结束了的历史节点finishedActivityInstancesList
         */
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
            // 获取流程节点
            // bpmnModel.getMainProcess()获取一个Process对象
            FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
            allHistoricActivityNodeList.add(flowNode);
        }
        // 循环活动节点
        for (FlowNode flowNode : allHistoricActivityNodeList) {
            // 获取每个活动节点的输入线
            List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();

            // 循环输入线，如果输入线的源头处于全部活动节点中，则将其包含在内
            for (SequenceFlow sequenceFlow : incomingFlows) {
                if (allHistoricActivityNodeList.stream().map(BaseElement::getId).collect(Collectors.toList()).contains(sequenceFlow.getSourceFlowElement().getId())){
                    highFlows.add(sequenceFlow.getId());
                }
            }
        }
        return highFlows;
    }
    private List<String> getRunningActivityFlowsIds(BpmnModel bpmnModel, List<String> runningActivityIdList, List<HistoricActivityInstance> historicActivityInstanceList) {
        List<String> runningActivityFlowsIds = new ArrayList<>();
        List<String> runningActivityIds = new ArrayList<>(runningActivityIdList);
        // 逆序寻找，因为historicActivityInstanceList有序
        if (CollectionUtils.isEmpty(runningActivityIds)) {
            return runningActivityFlowsIds;
        }
        for (int i = historicActivityInstanceList.size() - 1; i >= 0; i--) {
            HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i);
            FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
            // 如果当前节点是未完成的节点
            if (runningActivityIds.contains(flowNode.getId())) {
                continue;
            }
            // 当前节点的所有流出线
            List<SequenceFlow> outgoingFlowList = flowNode.getOutgoingFlows();
            // 遍历所有的流出线
            for (SequenceFlow outgoingFlow : outgoingFlowList) {
                // 获取当前节点流程线对应的下一级节点
                FlowNode targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(), true);
                // 如果找到流出线的目标是runningActivityIdList中的，那么添加后将其移除，避免找到重复的都指向runningActivityIdList的流出线
                if (runningActivityIds.contains(targetFlowNode.getId())) {
                    runningActivityFlowsIds.add(outgoingFlow.getId());
                    runningActivityIds.remove(targetFlowNode.getId());
                }
            }

        }
        return runningActivityFlowsIds;
    }


}